package ClassicalCryptography;

import java.util.HashMap;
import java.util.Map;

public class ClassicalCryptographyTest {
    public static void main(String[] args) {
        ClassicalCryptographyTest test = new ClassicalCryptographyTest();
        test.RailfenceCipherTest();
        test.MatrixCipherTest();
        test.MonoSubCipherTest();
        test.AffineCipherTest();
        test.VigenereCipherTest();
        test.VernamCipherTest();
    }

    public void RailfenceCipherTest() {
        String[][] testData = new String[2][3];
        testData[0][0] = "3";
        testData[0][1] = "whateverisworthdoingisworthdoingwell";
        testData[0][2] = "wtesrdnsrdneherwtogwtoglaviohiiohiwl";

        testData[1][0] = "2";
        testData[1][1] = "healthismoreimportantthanwealth";
        testData[1][2] = "hatimriprathnelhelhsoemotntawat*";

        boolean flag = true;
        for (int i = 0; i < testData.length; i++) {
            RailfenceCipher cipher = new RailfenceCipher(Integer.parseInt(testData[i][0]));
            String encryptData = cipher.encrypt(testData[i][1]);
            if (!encryptData.equals(testData[i][2])) {
                flag = false;
            }
            String decryptData = cipher.decrypt(encryptData);
            if (!decryptData.equals(testData[i][1])) {
                flag = false;
            }
        }
        if (flag) {
            System.out.println("RailfenceCipherTest：栅栏密码测试通过");
        } else {
            System.out.println("RailfenceCipherTest：栅栏密码测试不通过");
        }
    }

    public void MatrixCipherTest() {
        String[][] testData = new String[2][3];
        testData[0][0] = "6234517";
        testData[0][1] = "tobeornottobethatisaquestion";
        testData[0][2] = "reaootaebttseoitobsitohuntqn";

        testData[1][0] = "7345261";
        testData[1][1] = "ohtheworldhasbeenmadebyfools";
        testData[1][2] = "obeseaaohleytdnfhhmowsdloreb";

        boolean flag = true;
        for (int i = 0; i < testData.length; i++) {
            MatrixCipher cipher = new MatrixCipher();
            int[] key = new int[testData[i][0].length()];
            for (int keyIndex = 0; keyIndex < testData[i][0].length(); keyIndex++) {
                key[keyIndex] = Integer.parseInt("" + testData[i][0].charAt(keyIndex));
            }
            String encryptData = cipher.encrypt(testData[i][1], key);
            if (!encryptData.equals(testData[i][2])) {
                flag = false;
            }
            String decryptData = cipher.decrypt(encryptData, key);
            if (!decryptData.equals(testData[i][1])) {
                flag = false;
            }
        }
        if (flag) {
            System.out.println("MatrixCipherTest：矩阵密码测试通过");
        } else {
            System.out.println("MatrixCipherTest：矩阵密码测试不通过");
        }
    }

    public void MonoSubCipherTest() {
        String[][] testData = new String[2][2];
        testData[0][0] = "doyouwannatodance";
        testData[0][1] = "wbobmkqggqjbwqgzs";

        testData[1][0] = "youcanreallydance";
        testData[1][1] = "obmzqgnsqvvowqgzs";

        Map<Character, Character> keyBox = new HashMap<>();
        keyBox.put('a', 'q');
        keyBox.put('b', 'a');
        keyBox.put('c', 'z');
        keyBox.put('d', 'w');
        keyBox.put('e', 's');
        keyBox.put('f', 'x');
        keyBox.put('g', 'e');
        keyBox.put('h', 'd');
        keyBox.put('i', 'c');
        keyBox.put('j', 'r');
        keyBox.put('k', 'f');
        keyBox.put('l', 'v');
        keyBox.put('m', 't');
        keyBox.put('n', 'g');
        keyBox.put('o', 'b');
        keyBox.put('p', 'y');
        keyBox.put('q', 'h');
        keyBox.put('r', 'n');
        keyBox.put('s', 'u');
        keyBox.put('t', 'j');
        keyBox.put('u', 'm');
        keyBox.put('v', 'i');
        keyBox.put('w', 'k');
        keyBox.put('x', 'l');
        keyBox.put('y', 'o');
        keyBox.put('z', 'p');

        Map<Character, Character> invKeyBox = new HashMap<>();
        for (Character character : keyBox.keySet()) {
            invKeyBox.put(keyBox.get(character), character);
        }

        boolean flag = true;
        for (int i = 0; i < testData.length; i++) {
            MonoSubCipher cipher = new MonoSubCipher();
            String encryptData = cipher.encrypt(testData[i][0], keyBox);
            if (!encryptData.equals(testData[i][1])) {
                flag = false;
            }
            String decryptData = cipher.decrypt(encryptData, invKeyBox);
            if (!decryptData.equals(testData[i][0])) {
                flag = false;
            }
        }
        if (flag) {
            System.out.println("MonoSubCipherTest：单表代替密码测试通过");
        } else {
            System.out.println("MonoSubCipherTest：单表代替密码测试不通过");
        }
    }

    public void AffineCipherTest() {
        String[][] testData = new String[6][4];
        testData[0][0] = "3";
        testData[0][1] = "1";
        testData[0][2] = "iambuaaer";
        testData[0][3] = "zblejbbna";

        testData[1][0] = "5";
        testData[1][1] = "5";
        testData[1][2] = "beijinghuanyingni";
        testData[1][3] = "kztytsjobfsvtsjst";// kztytsjobfsytsjst

        testData[2][0] = "7";
        testData[2][1] = "10";
        testData[2][2] = "cryptography";
        testData[2][3] = "yzwlneazklhw";

        testData[3][0] = "9";
        testData[3][1] = "13";
        testData[3][2] = "seeyoutomorrow";
        testData[3][3] = "txxvjlcjrjkkjd";

        testData[4][0] = "15";
        testData[4][1] = "20";
        testData[4][2] = "thisisciphertext";
        testData[4][3] = "tvkekeyklvcptcbt";

        testData[5][0] = "2";
        testData[5][1] = "1";
        testData[5][2] = "abcdef";
        testData[5][3] = "报错";


        boolean flag = true;
        for (int i = 0; i < testData.length; i++) {
            AffineCipher cipher = new AffineCipher();
            String encryptData = null;
            try {
                encryptData = cipher.encrypt(testData[i][2], Integer.parseInt(testData[i][0]),
                        Integer.parseInt(testData[i][1]));
                if (!encryptData.equals(testData[i][3])) {
                    flag = false;
                }

                String decryptData = cipher.decrypt(encryptData, Integer.parseInt(testData[i][0]),
                        Integer.parseInt(testData[i][1]));
                if (!decryptData.equals(testData[i][2])) {
                    flag = false;
                }
            } catch (Exception e) {
                if (!testData[i][3].equals("报错")) {
                    flag = false;
                }
            }
        }
        if (flag) {
            System.out.println("AffineCipherTest：仿射密码测试通过");
        } else {
            System.out.println("AffineCipherTest：仿射密码测试不通过");
        }
    }

    public void VigenereCipherTest() {
        String[][] testData = new String[3][3];
        testData[0][0] = "deceptive";
        testData[0][1] = "wearediscoveredsaveyourself";
        testData[0][2] = "zicvtwqngrzgvtwavzhcqyglmgj";

        testData[1][0] = "chinese";
        testData[1][1] = "zhonghuaminzuweidafuxing";
        testData[1][2] = "bowakzyctqadmagplnjmbkuo";

        testData[2][0] = "music";
        testData[2][1] = "chenxingyinyueting";
        testData[2][2] = "obwvzuhygkzsmmvuhy";

        boolean flag = true;
        for (int i = 0; i < testData.length; i++) {
            VigenereCipher cipher = new VigenereCipher();
            String encryptData = cipher.encrypt(testData[i][1], testData[i][0]);
            if (!encryptData.equals(testData[i][2])) {
                flag = false;
            }
            String decryptData = cipher.decrypt(encryptData, testData[i][0]);
            if (!decryptData.equals(testData[i][1])) {
                flag = false;
            }
        }
        if (flag) {
            System.out.println("VigenereCipherTest：维吉尼亚密码测试通过");
        } else {
            System.out.println("VigenereCipherTest：维吉尼亚密码测试不通过");
        }
    }

    public void VernamCipherTest() {
        String[][] testData = new String[3][3];
        testData[0][0] = "f1571c94";
        testData[0][1] = "01234567";
        testData[0][2] = "f07459f3";

        testData[1][0] = "3475bd76fa040b73";
        testData[1][1] = "1b5e8b0f1bc78d23";
        testData[1][2] = "2f2b3679e1c38650";

        testData[2][0] = "2b24424b9fed596659842a4d0b007c61";
        testData[2][1] = "41b267bc5905f0a3cd691b3ddaee149d";
        testData[2][2] = "6a9625f7c6e8a9c594ed3170d1ee68fc";

        boolean flag = true;
        for (int i = 0; i < testData.length; i++) {
            VernamCipher cipher = new VernamCipher();
            String encryptData = cipher.encrypt(testData[i][1], testData[i][0]);
            if (!encryptData.equals(testData[i][2])) {
                flag = false;
            }
            String decryptData = cipher.decrypt(encryptData, testData[i][0]);
            if (!decryptData.equals(testData[i][1])) {
                flag = false;
            }
        }
        if (flag) {
            System.out.println("VernamCipherTest：弗纳姆密码测试通过");
        } else {
            System.out.println("VernamCipherTest：弗纳姆密码测试不通过");
        }
    }
}
